package com.ddh.codeduck.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddhcodeduck.common.exception.BusinessException;
import com.ddhcodeduck.common.exception.ErrorCode;
import com.ddhcodeduck.common.utils.PasswordUtil;
import com.ddhcodeduck.common.utils.UserContextHolder;
import com.ddhcodeduck.common.constant.UserRoleConstant;
import com.ddhcodeduck.common.constant.UserStatusConstant;
import com.codeduck.pojo.dto.CodeDuckUserDTO;
import com.codeduck.pojo.dto.CodeDuckUserPwdDTO;
import com.codeduck.pojo.entity.CodeDuckUser;
import com.ddh.codeduck.mapper.CodeDuckUserMapper;
import com.codeduck.pojo.req.CodeDuckUserPageReq;
import com.ddh.codeduck.service.ICodeDuckUserService;
import com.codeduck.pojo.vo.CodeDuckUserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author ddh
 * @since 2025-07-02
 */
@Service
public class CodeDuckUserServiceImpl extends ServiceImpl<CodeDuckUserMapper, CodeDuckUser> implements ICodeDuckUserService {

    /**
     * 用户注册
     *
     * @param CodeDuckUserRegisterDTO
     * @return
     */
    @Override
    public boolean register(CodeDuckUserDTO CodeDuckUserRegisterDTO) {
        // 1. 校验用户名是否已存在
        LambdaQueryWrapper<CodeDuckUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CodeDuckUser::getUsername, CodeDuckUserRegisterDTO.getUsername());
        if (this.count(queryWrapper) > 0) {
            throw new BusinessException(ErrorCode.USER_EXIST_ERROR);
        }
        // 2. 构建用户对象并加密密码
        //参数校验
        validateRegisterDTO(CodeDuckUserRegisterDTO);
        CodeDuckUser codeDuckUser = new CodeDuckUser();
        CodeDuckUserRegisterDTO.setPassword(PasswordUtil.encode(CodeDuckUserRegisterDTO.getPassword()));
        BeanUtils.copyProperties(CodeDuckUserRegisterDTO, codeDuckUser);
        // TODO: 文件上传后续实现,需要给一个默认头像
        codeDuckUser.setAvatarUrl("");
        codeDuckUser.setCreatedAt(LocalDateTime.now());
        codeDuckUser.setRole(UserRoleConstant.USER); // 默认普通用户
        codeDuckUser.setStatus(UserStatusConstant.ACTIVE); // 默认启用
        // 3. 保存用户
        return this.save(codeDuckUser);
    }

    /**
     * 用户登录
     *
     * @param loginDTO
     * @return
     */
    @Override
    public CodeDuckUserVO login(CodeDuckUserDTO loginDTO) {
        // 1. 参数校验
        if (loginDTO.getUsername() == null || loginDTO.getUsername().trim().isEmpty()) {
            throw new BusinessException(ErrorCode.USERNAME_EMPTY_ERROR);
        }
        if (loginDTO.getPassword() == null || loginDTO.getPassword().trim().isEmpty()) {
            throw new BusinessException(ErrorCode.PASSWORD_EMPTY_ERROR);
        }

        // 2. 查询用户
        LambdaQueryWrapper<CodeDuckUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CodeDuckUser::getUsername, loginDTO.getUsername());
        CodeDuckUser user = this.getOne(queryWrapper);

        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND_ERROR);
        }

        // 3. 密码验证
        if (!PasswordUtil.matches(loginDTO.getPassword(), user.getPassword())) {
            throw new BusinessException(ErrorCode.PASSWORD_ERROR);
        }

        // 4. 使用 Sa-Token 登录（自动绑定 userId 到 Token）
        StpUtil.login(user.getId());

        // 4.1 设置角色到 Session 中（供权限控制使用）
        StpUtil.getSession().set("role", user.getRole());

        // 5. 获取 Token（可返回给前端）
        String token = StpUtil.getTokenValue();

        // 6. 构建 VO 返回
        CodeDuckUserVO userVO = new CodeDuckUserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setToken(token);

        return userVO;
    }


    /**
     * 获取用户列表
     *
     * @return
     */
    @Override
    public IPage<CodeDuckUserVO> listUser(CodeDuckUserPageReq codeDuckUserPageReq) {
        int current = codeDuckUserPageReq.getCurrent();
        int pageSize = codeDuckUserPageReq.getPageSize();
        IPage<CodeDuckUser> page = new Page<>(current, pageSize);
        LambdaQueryWrapper<CodeDuckUser> queryWrapper = new LambdaQueryWrapper<>();
        if (codeDuckUserPageReq.getUsername() != null) {
            queryWrapper.like(CodeDuckUser::getUsername, codeDuckUserPageReq.getUsername());
        }
        if (codeDuckUserPageReq.getSortOrder() == "desc") {
            queryWrapper.orderByDesc(CodeDuckUser::getCreatedAt);
        } else if (codeDuckUserPageReq.getSortOrder() == "asc") {
            queryWrapper.orderByAsc(CodeDuckUser::getCreatedAt);
        }
        IPage<CodeDuckUser> userPage = page(page, queryWrapper);
        IPage<CodeDuckUserVO> voPage = userPage.convert(user -> {
            CodeDuckUserVO vo = new CodeDuckUserVO();
            BeanUtils.copyProperties(user, vo);
            return vo;
        });
        return voPage;
    }

    @Override
    public CodeDuckUserVO getByToken() {
        String userId = UserContextHolder.getUserId();
        if (userId == null) {
            throw new BusinessException(ErrorCode.TOKEN_INVALID_ERROR);
        }
        CodeDuckUser codeDuckUser = getById(userId);
        CodeDuckUserVO CodeDuckUserVO = new CodeDuckUserVO();
        BeanUtils.copyProperties(codeDuckUser, CodeDuckUserVO);
        return CodeDuckUserVO;
    }

    @Override
    public Boolean logout() {
        // 使用 Sa-Token 提供的登出方法
        StpUtil.logout();
        return true;
    }

    @Override
    public Boolean mySaveOrUpdate(CodeDuckUser codeDuckUser) {
        if (StrUtil.isNotEmpty(codeDuckUser.getPassword())) {
            //密码加密存储
            String encodePwd = PasswordUtil.encode(codeDuckUser.getPassword());
            codeDuckUser.setPassword(encodePwd);
        }
        return this.saveOrUpdate(codeDuckUser);
    }

    /**
     * 重置密码
     *
     * @param codeDuckUserPwdDTO
     * @return
     */
    @Override
    public Boolean resetPassword(CodeDuckUserPwdDTO codeDuckUserPwdDTO) {
        //判断旧密码是否正确
        CodeDuckUser codeDuckUser = this.getById(codeDuckUserPwdDTO.getId());
        //获取当前登录用户
        String userId = UserContextHolder.getUserId();
        //判断当前登录用户权限是不是管理员
        CodeDuckUser codeDuckUserCurrent = this.getById(userId);
        //如果是管理员不需要旧密码
        if (Objects.equals(codeDuckUserCurrent.getRole(), UserRoleConstant.ADMIN)) {
            codeDuckUser.setPassword(PasswordUtil.encode(codeDuckUserPwdDTO.getNewPassword()));
            return this.updateById(codeDuckUser);
        } else {
            //比较一下旧密码是否正确
            if (!PasswordUtil.matches(codeDuckUserPwdDTO.getPassword(), codeDuckUser.getPassword())) {
                //不正确->异常
                throw new BusinessException(ErrorCode.PASSWORD_ERROR);
            }
            codeDuckUser.setPassword(PasswordUtil.encode(codeDuckUserPwdDTO.getNewPassword()));
            //正确->修改
            return this.updateById(codeDuckUser);
        }
    }


    private void validateRegisterDTO(CodeDuckUserDTO CodeDuckUserRegisterDTO) {
        if (CodeDuckUserRegisterDTO.getUsername() == null || CodeDuckUserRegisterDTO.getUsername().trim().isEmpty()) {
            throw new BusinessException(ErrorCode.USERNAME_EMPTY_ERROR);
        }
        if (CodeDuckUserRegisterDTO.getPassword() == null || CodeDuckUserRegisterDTO.getPassword().trim().isEmpty()) {
            throw new BusinessException(ErrorCode.PASSWORD_EMPTY_ERROR);
        }
    }
}
